Skip to content

fix(sandbox): track PTY state per SSH channel to fix terminal resize#573

Open
cluster2600 wants to merge 1 commit intoNVIDIA:mainfrom
cluster2600:fix/543-pty-channel-tracking
Open

fix(sandbox): track PTY state per SSH channel to fix terminal resize#573
cluster2600 wants to merge 1 commit intoNVIDIA:mainfrom
cluster2600:fix/543-pty-channel-tracking

Conversation

@cluster2600
Copy link
Contributor

Summary

Resolves #543 — terminal resize (window_change_request) was broken when multiple SSH channels were open simultaneously.

  • Replace the flat pty_master/input_sender/pty_request fields in SshHandler with a HashMap<ChannelId, ChannelState>, ensuring each channel tracks its own PTY resources independently
  • Fix set_winsize to pass a reference (&winsize) to ioctl, correcting undefined behaviour on aarch64
  • Add error logging when set_winsize fails, rather than silently discarding the result

Root Cause

The previous implementation stored a single pty_master file descriptor at the handler level. When a client opened multiple channels (e.g. parallel shells, shell + SFTP), window_change_request would resize whichever PTY was stored last — not the one belonging to the requesting channel.

graph TD
    subgraph "Before (broken)"
        A[Channel 0 — resize 80×24] --> B[SshHandler.pty_master]
        C[Channel 1 — resize 120×50] --> B
        B --> D["ioctl(TIOCSWINSZ) on last-stored FD"]
    end

    subgraph "After (fixed)"
        E[Channel 0 — resize 80×24] --> F["channels[0].pty_master"]
        G[Channel 1 — resize 120×50] --> H["channels[1].pty_master"]
        F --> I["ioctl(TIOCSWINSZ) on channel 0 FD"]
        H --> J["ioctl(TIOCSWINSZ) on channel 1 FD"]
    end
Loading

Changes

File Change
crates/openshell-sandbox/src/ssh.rs Introduce ChannelState struct; migrate all per-channel fields into HashMap<ChannelId, ChannelState>; update pty_request_request, window_change_request, data, channel_eof, subsystem_request, and spawn_shell_or_exec to look up channel state by ID

Test Plan

  • cargo test -p openshell-sandbox — 319 passed (1 pre-existing failure in drop_privileges, unrelated)
  • New test: set_winsize_applies_to_correct_pty — verifies two PTYs can be resized independently
  • New test: channel_state_independent_input_senders — verifies data routing and EOF isolation between channels
sequenceDiagram
    participant Client
    participant SshHandler
    participant Channel0
    participant Channel1

    Client->>SshHandler: pty_request(channel=0, 80×24)
    SshHandler->>Channel0: store PTY master + request

    Client->>SshHandler: pty_request(channel=1, 120×50)
    SshHandler->>Channel1: store PTY master + request

    Client->>SshHandler: window_change(channel=0, 132×43)
    SshHandler->>Channel0: ioctl(TIOCSWINSZ, 132×43)
    Note over Channel1: unaffected

    Client->>SshHandler: channel_eof(channel=0)
    SshHandler->>Channel0: drop input_sender
    Note over Channel1: still functional
Loading

@cluster2600 cluster2600 requested a review from a team as a code owner March 24, 2026 20:56
@drew drew self-assigned this Mar 25, 2026
@github-actions
Copy link

Thank you for your interest in contributing to OpenShell, @cluster2600.

This project uses a vouch system for first-time contributors. Before submitting a pull request, you need to be vouched by a maintainer.

To get vouched:

  1. Open a Vouch Request discussion.
  2. Describe what you want to change and why.
  3. Write in your own words — do not have an AI generate the request.
  4. A maintainer will comment /vouch if approved.
  5. Once vouched, open a new PR (preferred) or reopen this one after a few minutes.

See CONTRIBUTING.md for details.

@github-actions github-actions bot closed this Mar 25, 2026
@github-actions
Copy link

Thank you for your submission! We ask that you sign our Developer Certificate of Origin before we can accept your contribution. You can sign the DCO by adding a comment below using this text:


I have read the DCO document and I hereby sign the DCO.


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the DCO Assistant Lite bot.

@drew drew reopened this Mar 25, 2026
@cluster2600
Copy link
Contributor Author

I have read the DCO document and I hereby sign the DCO.

@cluster2600 cluster2600 force-pushed the fix/543-pty-channel-tracking branch from 834c075 to 72892c7 Compare March 25, 2026 15:45
window_change_request previously applied resize to a single shared
pty_master field, ignoring the channel ID. When multiple channels were
open, resize requests would affect the wrong terminal or be lost
entirely.

Replace the flat pty_master/input_sender/pty_request fields in
SshHandler with a HashMap<ChannelId, ChannelState> so each channel
tracks its own PTY master, input sender, and pending PTY request.
This ensures window_change_request, data, and channel_eof all
operate on the correct channel.

Closes NVIDIA#543
@cluster2600 cluster2600 force-pushed the fix/543-pty-channel-tracking branch from 72892c7 to 8c9f987 Compare March 25, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(ssh): window-change requests not applied to remote PTY — terminal resize broken

3 participants